Skip to content

Add enums_in_transition support for gradual enum migration#1093

Draft
ashkan25 wants to merge 3 commits intoblock:mainfrom
ashkan25:ashkan25/enum-transition-support
Draft

Add enums_in_transition support for gradual enum migration#1093
ashkan25 wants to merge 3 commits intoblock:mainfrom
ashkan25:ashkan25/enum-transition-support

Conversation

@ashkan25
Copy link
Copy Markdown

@ashkan25 ashkan25 commented Mar 25, 2026

Summary

When type_name_overrides is used to collapse input enum names onto output enum names (e.g., "ColorInput" => "Color"), the standard 3-stage enum value migration becomes impossible — removing the override simultaneously renames all filter field types, breaking all clients at once with no transition period.

This PR adds an enums_in_transition configuration option that enables gradual migration:

  • Generates a transition *Input enum type alongside the collapsed output enum
  • Adds an equalToAnyOfInput filter field that accepts the new input enum type
  • Processes equalToAnyOfInput identically to equalToAnyOf at runtime (same ES terms query, same null handling, same shard routing optimization)
  • Validates that enums_in_transition names match defined enum types, with DidYouMean suggestions

Migration workflow this enables

  1. Add enum to enums_in_transition — schema gains ColorInput enum and equalToAnyOfInput filter field
  2. Clients migrate from equalToAnyOf: [Color] to equalToAnyOfInput: [ColorInput] at their own pace
  3. Remove the type_name_overrides entry — equalToAnyOf now naturally uses [ColorInput]
  4. Clients migrate back to equalToAnyOf (or keep using equalToAnyOfInput as a permanent alias)
  5. Remove enum from enums_in_transition

Key mechanisms

  • skip_name_override on EnumType constructor — bypasses type_name_overrides for transition input enum creation
  • type_already_final on Field — bypasses to_final_form for filter field type resolution
  • Shared lambda in FilterNodeInterpreter for both equalToAnyOf and equalToAnyOfInput
  • RoutingPicker, IndexExpressionBuilder, and Filters all handle the new operator for shard routing and index pruning
  • Apollo and Warehouse factory extensions forward **kwargs so skip_name_override reaches the base method
  • All RBS type signatures updated for new parameters and methods

Test plan

  • All existing elasticgraph-schema_definition unit tests pass (1620 examples)
  • All existing elasticgraph-graphql unit tests pass (1336 examples)
  • All existing elasticgraph-schema_artifacts unit tests pass (105 examples)
  • New tests verify transition input enum generation with type_name_overrides active
  • New tests verify equalToAnyOfInput filter field on both standard and list element filter types
  • New tests verify no transition types generated when enum is not in enums_in_transition
  • Tests run with both camelCase and snake_case casing forms
  • Integration tests with a running datastore (pending)

When EG subgraphs use type_name_overrides to collapse input enum names
(e.g. PaymentStatusInput -> PaymentStatus), the standard 3-stage enum
migration becomes impossible. This adds an `enums_in_transition`
configuration that enables a transition period:

- Generates a transition InputEnum type alongside the collapsed output enum
- Adds an `equalToAnyOfInput` filter field that accepts the input enum
- Processes `equalToAnyOfInput` identically to `equalToAnyOf` at runtime

Key mechanisms:
- `skip_name_override` on EnumType bypasses type_name_overrides for
  transition input enum creation
- `type_already_final` on Field bypasses to_final_form for filter field
  type resolution
- Shared lambda in FilterNodeInterpreter for both operators

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

- Fix routing/index optimization gap: RoutingPicker, IndexExpressionBuilder,
  and Filters now handle :equal_to_any_of_input the same as :equal_to_any_of,
  ensuring shard routing and rollover index pruning work for the new operator
- Add missing RBS type signature for equal_to_any_of_input
- Add validation warning when enums_in_transition contains names that don't
  match any defined enum type (with DidYouMean suggestions)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Copy Markdown
Collaborator

@myronmarston myronmarston left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write up a proposal for this as a discussion? I'd like to the context for the problem you're trying to solve, the options you considered, why you chose this option, etc.

In general, we ask that anything with interesting design choices and tradeoffs start as a proposal.

… up test names

- Forward **kwargs in Apollo and Warehouse factory extensions so
  skip_name_override reaches the base Factory#new_enum_type method
- Add missing RBS type signatures for enums_in_transition, skip_name_override,
  type_already_final, and notify_about_unrecognized_enums_in_transition
- Replace lambda-in-string test names with plain strings

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants